#include "tcpmgr.h"
#include <QAbstractSocket>
#include <QJsonDocument>
#include <QJsonObject>
#include "usermgr.h"
TcpMgr::~TcpMgr()
{
    _socket.close();
}

void TcpMgr::slot_tcp_connect(ServerInfo si)
{
    qDebug() << "Receive tcp connect signal";
    qDebug() << "Connecting to server ...";
    _host = si.Host;
    _port = si.Port.toUInt();
    _socket.connectToHost(_host, _port);
}

void TcpMgr::slot_send_data(ReqId reqId, QByteArray data)
{
    uint16_t id = static_cast<uint16_t>(reqId);
    // 计算长度 （使用网络字节序转换）
    quint16 len = static_cast<quint16>(data.size());
    // 创建一个QByteArray 用于存储要发送的所有数据
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    // 设置数据流使用网络字节序
    out.setByteOrder(QDataStream::BigEndian);
    // 写入ID、长度和数据
    qDebug() << "id: " << id << "len: " << len << " data: " << data;
    out << id << len;
    block.append(data);
    _socket.write(block);
}

TcpMgr::TcpMgr()
    : _host("")
    , _port(0)
    , _b_recv_pending(false)
    , _message_id(0)
    , _message_len(0)
{
    connect(&_socket, &QTcpSocket::connected, this, [&]() {
        qDebug() << "Connected to server!";
        emit sig_con_success(true);
    });
    connect(&_socket, &QTcpSocket::readyRead, this, [&]() {
        // 当有数据可读时，读取所有数据
        _buffer.clear();
        _buffer.append(_socket.readAll());
        QDataStream stream(&_buffer, QIODevice::ReadOnly);
        stream.setVersion(QDataStream::Qt_6_2);
        stream.setByteOrder(QDataStream::BigEndian);
        forever {
            // 先解析头部
            if (!_b_recv_pending) {
                // 检查缓冲区中的数据是否足够解析出一个消息头(消息ID + 消息长度)
                if (_buffer.size() < static_cast<int>(sizeof(quint16) * 2)) {
                    return; //数据不够，等待更多数据
                }
                // 预读取消息ID和消息长度，但不从缓冲区中移除
                stream >> _message_id >> _message_len;
                // 输出读取的数据
                qDebug() << "Message ID: " << _message_id << ", Length: " << _message_len;
            }
            // buffer 剩余长度是否满足消息体长度，不满足则退出继续等待接受
            if (_buffer.size() < _message_len + sizeof(quint16) * 2) {
                _b_recv_pending = true;
                return;
            }
            _b_recv_pending = false;
            // 读取消息体
            QByteArray messageBody = _buffer.mid(sizeof(quint16) * 2, _message_len);
            _buffer.clear();
            // 处理消息
            handleMsg(ReqId(_message_id), _message_len, messageBody);
        }
    });
    // 错误处理
    connect(&_socket, &QTcpSocket::errorOccurred, this, [&](QAbstractSocket::SocketError error) {
        qDebug() << "Error is : " << error;
        switch (error) {
        case QAbstractSocket::ConnectionRefusedError:
            qDebug() << "Connection Refused!";
            emit sig_con_success(false);
            break;
        case QAbstractSocket::RemoteHostClosedError:
            qDebug() << "Remote Host Closed Connection!";
            break;
        case QAbstractSocket::HostNotFoundError:
            qDebug() << "Host not Found!";
            emit sig_con_success(false);
            break;
        case QAbstractSocket::SocketTimeoutError:
            qDebug() << "Connection Timeout!";
            emit sig_con_success(false);
            break;
        case QAbstractSocket::NetworkError:
            qDebug() << "Network Error!";
            break;
        default:
            qDebug() << "Other Error!";
            break;
        }
    });
    // 处理连接断开
    connect(&_socket, &QTcpSocket::disconnected, this, []() {
        qDebug() << "Disconnected from server.";
    });
    // 连接发送信号，用于发送数据
    connect(this, &TcpMgr::sig_send_data, this, &TcpMgr::slot_send_data);
    // 注册消息
    initHandlers();
}

void TcpMgr::initHandlers()
{
    // 用户登录回包处理
    _handlers.insert(ID_CHAT_LOGIN_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "Login Failed, error is Json Parse Error " << err;
            emit sig_login_failed(err);
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "Login Falied, error is " << err;
            emit sig_login_failed(err);
            return;
        }

        std::shared_ptr<UserInfo> userInfo = std::make_shared<UserInfo>();
        userInfo->token = jsonObj["token"].toString();
        userInfo->name = jsonObj["name"].toString();
        userInfo->uid = jsonObj["uid"].toInt();
        userInfo->email = jsonObj["email"].toString();
        if (jsonObj.contains("icon") && !jsonObj["icon"].toString().isEmpty()) {
            userInfo->icon = jsonObj["icon"].toString();
        } else {
            userInfo->icon = GetRandomIcon();
        }
        UserMgr::GetInstance()->SetUserInfo(userInfo);
        // 加载好友
        if (jsonObj.contains("friends")) {
            UserMgr::GetInstance()->AddFriendList(jsonObj["friends"].toArray());
        }
        // 加载好友申请数据
        if (jsonObj.contains("apply_list")) {
            UserMgr::GetInstance()->AddApplyList(jsonObj["apply_list"].toArray());
        }
        // 好友消息
        if (jsonObj.contains("message_list")) {
            QVector<QString> msg_id_list;
            UserMgr::GetInstance()->AddMessageList(jsonObj["message_list"].toArray(), msg_id_list);
            QJsonObject rtvalue;
            rtvalue["touid"] = userInfo->uid;
            QJsonArray jsonArray;
            for (auto &msg_id : msg_id_list) {
                jsonArray.append(msg_id);
            }
            rtvalue["msg_ids"] = jsonArray;
            jsonDoc = QJsonDocument(rtvalue);
            QByteArray rtdata = jsonDoc.toJson(QJsonDocument::Compact);
            // 给服务器发送消息 确认消息已收到
            emit sig_send_data(ID_TEXT_CHAT_MSG_RSP, rtdata);
        }
        emit sig_switch_chatdlg();
        
    });

    // 搜索结果回包处理
    _handlers.insert(ID_SEARCH_USER_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            emit sig_user_search(nullptr);
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "User search failed, error is Json Parse Error " << err;
            emit sig_user_search(nullptr);
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "User search falied, error is " << err;
            emit sig_user_search(nullptr);
            return;
        }
        auto searchInfo = std::make_shared<SearchInfo>(jsonObj["uid"].toInt(),
                                                       jsonObj["name"].toString(),
                                                       jsonObj["nick"].toString(),
                                                       jsonObj["desc"].toString(),
                                                       jsonObj["sex"].toInt(),
                                                       jsonObj["icon"].toString());
        emit sig_user_search(searchInfo);
    });

    // 好友申请回包
    _handlers.insert(ID_ADD_FRIEND_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "Send add friend request failed, error is Json Parse Error " << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "Send add friend request falied, error is " << err;
            return;
        }
        qDebug() << "Send add friend request success!\n";
    });

    // 收到添加好友请求
    _handlers.insert(ID_NOTIFY_ADD_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "Recive add friend request failed, error is Json Parse Error " << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "Recive add friend request falied, error is " << err;
            return;
        }
        // 获取信息
        int fromuid = jsonObj["applyuid"].toInt();
        QString name = jsonObj["name"].toString();
        QString desc = jsonObj["desc"].toString();
        qDebug() << "Recive add friend request.\n"
                 << " name: " << name << ", fromuid: " << fromuid << ", desc: " << desc << ".\n";
        // int from_uid, QString name, QString desc, QString icon, QString nick, int sex
        auto applyInfo = std::make_shared<AddFriendApply>(fromuid, name, desc, "", "", 0);
        emit sig_friendApply(applyInfo);
    });

    // 对方同意添加好友
    _handlers.insert(ID_NOTIFY_AUTH_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "Recive friend agree request failed, error is Json Parse Error " << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "Recive friend agree request failed, error is " << err;
            return;
        }
        // 获取信息
        int fromuid = jsonObj["uid"].toInt();
        // 好友昵称
        QString name = jsonObj["name"].toString();
        // 好友申请时的备注
        QString remark = jsonObj["remark"].toString();
        // 好友头像
        QString icon = jsonObj["icon"].toString();
        int sex = jsonObj["sex"].toInt();

        qDebug() << "Received a reply agreeing to add friends.\n"
                 << " name: " << name << ", fromuid: " << fromuid << ", remark: " << remark
                 << ", sex:" << sex << ".\n";
        // int uid, QString name, QString remark, QString icon, QString desc, int sex
        auto authInfo = std::make_shared<AuthInfo>(fromuid, name, remark, icon, "", sex);
        // 添加认证好友到联系人列表
        emit sig_addAuthFriend(authInfo);
    });

    // 同意添加对方好友回包
    _handlers.insert(ID_AUTH_FRIEND_RSP, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        if (!jsonObj.contains("error")) {
            int err = ErrorCode::ERROR_JSON;
            qDebug() << "Recive friend agree request failed, error is Json Parse Error " << err;
            return;
        }
        int err = jsonObj["error"].toInt();
        if (err != ErrorCode::SUCCESS) {
            qDebug() << "Recive friend agree request failed, error is " << err;
            return;
        }
        // 获取信息
        int touid = jsonObj["uid"].toInt();
        // 好友昵称
        QString name = jsonObj["name"].toString();
        // 好友申请时的备注
        QString remark = jsonObj["remark"].toString();
        // 好友头像
        QString icon = jsonObj["icon"].toString();
        int sex = jsonObj["sex"].toInt();

        qDebug() << "Auth friend success.\n"
                 << " name: " << name << " icon:" << icon << ", touid: " << touid
                 << ", remark: " << remark << ", sex:" << sex << ".\n";
        auto authInfo = std::make_shared<AuthRsp>(touid, name, remark, icon, "", sex);
        // 发送同意认证信号
        emit sig_authRsp(authInfo);
    });

    // 收到好友文本消息
    _handlers.insert(ID_TEXT_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) {
        Q_UNUSED(len);
        qDebug() << "handle id is " << id << " data is " << data;
        // 将QByteArray转换为QJsonDocument
        QJsonDocument jsonDoc = QJsonDocument::fromJson(data);
        // 检查是否转换成功
        if (jsonDoc.isNull()) {
            qDebug() << "Failed to create QJsonDocument.";
            return;
        }
        QJsonObject jsonObj = jsonDoc.object();
        // 发送者uid
        int fromuid = jsonObj["fromuid"].toInt();
        // 接收者uid
        int touid = jsonObj["touid"].toInt();
        // 消息内容
        QString message = jsonObj["message"].toString();
        // 消息发送时间
        QString send_time = jsonObj["send_time"].toString();
        // 消息id
        QString msg_id = jsonObj["msg_id"].toString();

        qDebug() << "Receive friend message.\n"
                 << " fromuid: " << fromuid << " message:" << message
                 << ", send_time: " << send_time << ".\n";
        std::shared_ptr<TextChatData> textChatData = std::make_shared<TextChatData>();
        textChatData->from_uid = fromuid;
        textChatData->msg_id = msg_id;
        textChatData->msg_content = message;
        textChatData->to_uid = touid;
        textChatData->send_time = send_time;
        emit sig_hasNewTextMessage(textChatData);
        // 发送收到消息回包
        QJsonObject rtvalue;
        rtvalue["touid"] = touid;
        QJsonArray jsonArray;
        jsonArray.append(msg_id);
        rtvalue["msg_ids"] = jsonArray;
        jsonDoc = QJsonDocument(rtvalue);
        QByteArray rtdata = jsonDoc.toJson(QJsonDocument::Compact);
        // 给服务器发送消息 确认消息已收到
        emit sig_send_data(ID_TEXT_CHAT_MSG_RSP, rtdata);
        
    });
}

void TcpMgr::handleMsg(ReqId id, int len, QByteArray data)
{
    auto find_iter = _handlers.find(id);
    if (find_iter == _handlers.end()) {
        qDebug() << "Not found id [" << id << "] to handle";
        return;
    }
    find_iter.value()(id, len, data);
}
